﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace CQSDK
{
	public class CQAPP
	{
		public int AuthCode { get; set; }
		private string AppDirectory;
		public bool 应用已启用 { get; set; }
		public const int 消息忽略 = 0;
		public const int 消息拦截 = 1;

		private static readonly Encoding GB18030 = Encoding.GetEncoding(54936);

		/// <summary>
		/// 发送群消息
		/// </summary>
		/// <param name="groupid"></param>
		/// <param name="msg"></param>
		/// <returns></returns>
		public int SendGroupMessage(long groupid, string msg)
		{
			return CQAPI.SendGroupMessage(AuthCode, groupid, GB18030.GetBytes(msg));
		}

		/// <summary>
		/// 发送私聊消息
		/// </summary>
		/// <param name="QQID"></param>
		/// <param name="msg"></param>
		/// <returns></returns>
		public int SendPrivateMessage(long QQID, string msg)
		{
			return CQAPI.SendPrivateMessage(AuthCode, QQID, GB18030.GetBytes(msg));
		}

		/// <summary>
		/// 发送讨论组信息
		/// </summary>
		/// <param name="讨论组号"></param>
		/// <param name="msg"></param>
		/// <returns></returns>
		public long SendDiscussMessage(long 讨论组号, string msg)
		{
			return CQAPI.SendDiscussMessage(AuthCode, 讨论组号, GB18030.GetBytes(msg));
		}

		/// <summary>
		/// CQ码_AT
		/// </summary>
		/// <param name="QQID"></param>
		/// <returns></returns>
		public string Code_AT(long QQID)
		{
			if (QQID == -1)
			{
				return "[CQ:at,qq=all] ";
			}
			return string.Format("[CQ:at,qq={0}] ", QQID);
		}

		/// <summary>
		/// CQ码_窗口抖动
		/// </summary>
		/// <returns></returns>
		public string Code_Shake()
		{
			return "[CQ:shake]";
		}

		/// <summary>
		/// CQ码_表情
		/// </summary>
		/// <param name="ID"></param>
		/// <returns></returns>
		public string Code_Emoji(int ID)
		{
			return string.Format("[CQ:emoji,id={0}]", ID);
		}

		public string CQ码_反转义(string msg)
		{
			string str = msg;
			str.Replace("&#91;", "[");
			str.Replace("&#93;", "]");
			str.Replace("&#44;", ",");
			str.Replace("&amp;", "&");
			return str;
		}

		public string CQ码_转义(string msg)
		{
			string str = msg;
			str.Replace("[", "&#91;");
			str.Replace("]", "&#93;");
			str.Replace(",", "&#44;");
			str.Replace("&", "&amp;");
			return str;
		}

		/// <summary>
		/// CQ码_链接分享
		/// </summary>
		/// <param name="url"></param>
		/// <param name="title"></param>
		/// <param name="content"></param>
		/// <param name="image"></param>
		/// <returns></returns>
		public string Code_UrlShare(string url, string title, string content, string image)
		{
			string part = string.Concat(",url=", CQ码_转义(url));
			if (title != "")
			{
				part += string.Format(",title=", CQ码_转义(title));
			}
			if (content != "")
			{
				part += string.Format(",content=", CQ码_转义(content));
			}
			if (image != "")
			{
				part += string.Format(",image=", CQ码_转义(image));
			}
			return string.Format("[CQ:share{0}]", part);
		}

		/// <summary>
		/// CQ码_名片分享
		/// </summary>
		/// <param name="type"></param>
		/// <param name="id"></param>
		/// <returns></returns>
		public string CQ码_名片分享(string type, long id)
		{
			return string.Format("[CQ:contact,type={0},id={1}]", CQ码_转义(type), id);
		}

		/// <summary>
		/// CQ码_匿名
		/// </summary>
		/// <param name="是否不强制"></param>
		/// <returns></returns>
		public string Code_Anonymous(bool 是否不强制)
		{
			return string.Format("[CQ:anonymous{0}]", 是否不强制 ? ",ignore=true" : "");
		}

		/// <summary>
		/// CQ码_图片
		/// </summary>
		/// <param name="file"></param>
		/// <returns></returns>
		public string Code_Image(string file)
		{
			return string.Format("[CQ:image,file={0}]", CQ码_转义(file));
		}

		/// <summary>
		/// CQ码_位置分享
		/// </summary>
		/// <param name="纬度"></param>
		/// <param name="经度"></param>
		/// <param name="放大倍数"></param>
		/// <param name="地点名称"></param>
		/// <param name="地址"></param>
		/// <returns></returns>
		public string Code_PlaceShare(double 纬度, double 经度, int 放大倍数, string 地点名称, string 地址)
		{
			string para = string.Format(",lat{0},lon{1}", 纬度, 经度);
			if (放大倍数 > 0)
			{

				para += string.Concat(",zoom", 放大倍数);
			}
			para += string.Format(",title={0},content={1}", CQ码_转义(地点名称), CQ码_转义(地址));
			return string.Concat("[CQ:location", para, "]");
		}

		/// <summary>
		/// 取群成员信息
		/// </summary>
		/// <param name="GroupId"></param>
		/// <param name="QQID"></param>
		/// <param name="GroupMember"></param>
		/// <param name="不使用缓存"></param>
		/// <returns>0代表成功，小于0代表失败</returns>
		public bool GetGroupMemberInfo(long GroupId, long QQID, out GroupMemberInfo GroupMember, bool 不使用缓存 = false)
		{
			GroupMember = new GroupMemberInfo();
			string re = CQAPI.GetGroupMemberInfo(AuthCode, GroupId, QQID, 不使用缓存);
			if (string.IsNullOrEmpty(re)) return false;

			var bytes = Decoding_BASE64(re);
			if (bytes == null || bytes.Length < 40) return false;

			UnPack u = new UnPack(bytes);
			GroupMember.GroupNumber = u.GetLong();
			GroupMember.QQID = u.GetLong();
			GroupMember.QQNick = u.GetLenStr();
			GroupMember.GroupCard = u.GetLenStr();
			GroupMember.Gender = u.GetInt();
			GroupMember.Age = u.GetInt();
			GroupMember.Arge = u.GetLenStr();
			GroupMember.AddGroupTime = u.GetInt();
			GroupMember.LastSpeakTime = u.GetInt();
			GroupMember.LevelName = u.GetLenStr();
			GroupMember.管理权限 = u.GetInt();
			GroupMember.不良记录成员 = u.GetInt() == 1;
			GroupMember.专属头衔 = u.GetLenStr();
			GroupMember.专属头衔过期时间 = u.GetInt();
			GroupMember.允许修改名片 = u.GetInt() == 1;
			return true;
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="GroupId"></param>
		/// <param name="groupMemberInfos"></param>
		/// <returns></returns>
		public bool GetGroupMemberList(long GroupId, out List<GroupMemberInfo> groupMemberInfos)
		{
			groupMemberInfos = new List<GroupMemberInfo>();
			string re = CQAPI.GetGroupMemberList(AuthCode, GroupId);
			if (string.IsNullOrEmpty(re))
			{
				return false;
			}
			byte[] by = Decoding_BASE64(re);
			if (by == null && by.Length < 4)
			{
				return false;
			}
			var temp = new UnPack(by);
			int count = temp.GetInt();
			for (int i = 0; i < count; i++)
			{
				if (temp.Len() <= 0) return false;
				var u = new UnPack(temp.GetToken());

				var GroupMember = new GroupMemberInfo();
				GroupMember.GroupNumber = u.GetLong();
				GroupMember.QQID = u.GetLong();
				GroupMember.QQNick = u.GetLenStr();
				GroupMember.GroupCard = u.GetLenStr();
				GroupMember.Gender = u.GetInt();
				GroupMember.Age = u.GetInt();
				GroupMember.Arge = u.GetLenStr();
				GroupMember.AddGroupTime = u.GetInt();
				GroupMember.LastSpeakTime = u.GetInt();
				GroupMember.LevelName = u.GetLenStr();
				GroupMember.管理权限 = u.GetInt();
				GroupMember.不良记录成员 = u.GetInt() == 1;
				GroupMember.专属头衔 = u.GetLenStr();
				GroupMember.专属头衔过期时间 = u.GetInt();
				GroupMember.允许修改名片 = u.GetInt() == 1;

				groupMemberInfos.Add(GroupMember);
			}
			return true;
		}

		public int GetCsrfToken()
		{
			return CQAPI.GetCsrfToken(AuthCode);
		}

		public string GetCookies()
		{
			return CQAPI.GetCookies(AuthCode);
		}

		/// <summary>
		/// 取登录QQ
		/// </summary>
		/// <returns></returns>
		public long GetLoginQQ()
		{
			return CQAPI.GetLoginQQ(AuthCode);
		}

		/// <summary>
		/// 取登录昵称
		/// </summary>
		/// <returns></returns>
		public string GetLoginNick()
		{
			return CQAPI.GetLoginNick(AuthCode);
		}

		/// <summary>
		/// 获取QQ信息
		/// </summary>
		/// <param name="qqId">目标QQ</param>
		/// <param name="qqInfo">返回QQ信息, 若获取失败, 返回null</param>
		/// <param name="notCache">不使用缓存, 默认为"False"，通常忽略本参数，仅在必要时使用</param>
		/// <returns></returns>
		public bool GetQQInfo(long qqId, out QQInfo qqInfo, bool notCache = false)
		{
			qqInfo = new QQInfo();
			string result = CQAPI.GetStrangerInfo(AuthCode, qqId, notCache);
			if (string.IsNullOrEmpty(result))
			{
				return false;
			}
			UnPack unpack = new UnPack(Convert.FromBase64String(result));		
			qqInfo.Id = unpack.GetLong();
			qqInfo.Nick = unpack.GetLenStr();
			qqInfo.Sex = (Sex)unpack.GetInt();
			qqInfo.Age = unpack.GetInt();
			return true;
		}

		public bool GetFriendList(out List<FriendInfo> friendInfo)
		{
			friendInfo = new List<FriendInfo>();
			var re = CQAPI.GetFriendList(AuthCode, false);
			if (string.IsNullOrWhiteSpace(re)) return false;

			var data = Decoding_BASE64(re);
			if (data == null || data.Length < 4) return false;

			var u = new UnPack(data);
			int count = u.GetInt();

			for (int i = 0; i < count; i++)
			{
				if (u.Len() <= 0) return false;
				var temp = new UnPack(u.GetToken());
				var infotemp = new FriendInfo();
				infotemp.Id = temp.GetLong();
				infotemp.Nick = temp.GetLenStr();
				infotemp.Remarks = temp.GetLenStr();
				friendInfo.Add(infotemp);
			}
			return true;
		}

		/// <summary>
		/// 取群列表
		/// </summary>
		/// <param name="groupInfos"></param>
		/// <returns>返回群数量,0表示失败</returns>
		public bool GetGroupList(out List<GroupInfo> GroupList)
		{
			GroupList = new List<GroupInfo>();
			string bin = CQAPI.GetGroupList(AuthCode);			
			if (string.IsNullOrEmpty(bin)) return false;
			byte[] vs = Decoding_BASE64(bin);
			if (vs.Length < 4) return false;

			UnPack unpack = new UnPack(vs);
			int count = unpack.GetInt();
			for (int i = 0; i < count; i++)
			{
				GroupInfo temp = new GroupInfo();
				if (unpack.Len() <= 0) return false;

				byte[] ansihex = unpack.GetToken();
				UnPack u = new UnPack(ansihex);

				temp.GroupNumber = u.GetLong();
				temp.GroupName = u.GetLenStr();

				GroupList.Add(temp);
			}
			return true;
		}

		/// <summary>
		/// 取群信息
		/// </summary>
		/// <param name="Qun"></param>
		/// <param name="reserved"></param>
		/// <returns></returns>
		public bool GetGroupInfo(long Qun,out GroupInfo groupInfo ,bool reserved = false)
		{
			groupInfo = new GroupInfo();
			var re = CQAPI.GetGroupInfo(AuthCode, Qun, reserved);
			if (string.IsNullOrWhiteSpace(re)) return false;
			var data = Decoding_BASE64(re);
			if (data == null || data.Length < 18) return false;
			var u = new UnPack(data);
			groupInfo.GroupNumber = u.GetLong();
			groupInfo.GroupName = u.GetLenStr();
			groupInfo.Now = u.GetInt();
			groupInfo.Max = u.GetInt();
			return true;
		}

		/// <summary>
		/// 取应用目录
		/// </summary>
		/// <returns></returns>
		public string GetAppFolder()
		{
			if (!string.IsNullOrEmpty(AppDirectory)) return AppDirectory;
			AppDirectory = CQAPI.GetCQAppFolder(AuthCode);
			if (!Directory.Exists(AppDirectory)) Directory.CreateDirectory(AppDirectory);
			return AppDirectory;
		}

		/// <summary>
		/// 接收图片，返回图片绝对路径
		/// </summary>
		/// <param name="file">CQ码中的图片名称(file)</param>
		/// <returns></returns>
		public bool GetImage(string file,out string outfile)
		{
			outfile = CQAPI.GetImage(AuthCode, file);
			if (string.IsNullOrWhiteSpace(outfile)) return false;
			return true;
		}

		/// <summary>
		/// 撤回信息
		/// </summary>
		/// <param name="msgid"></param>
		/// <returns></returns>
		public int DeleteMessage(long msgid)
		{
			return CQAPI.DeleteMessage(AuthCode, msgid);
		}

		/// <summary>
		/// 设置群成员禁言
		/// </summary>
		/// <param name="groupid"></param>
		/// <param name="QQID"></param>
		/// <param name="duration">单位为秒，0为解禁</param>
		/// <returns></returns>
		public int SetGroupBan(long groupid, long QQID, long duration)
		{
			return CQAPI.SetGroupBan(AuthCode, groupid, QQID, duration);
		}

		/// <summary>
		/// 移除群成员
		/// </summary>
		/// <param name="GroupID"></param>
		/// <param name="QQID"></param>
		/// <param name="flag">如果为真，则"不再接收此人加群申请"，请慎用。留空为假</param>
		/// <returns></returns>
		public int SetGroupKick(long GroupID, long QQID, bool rejectaddrequest = false)
		{
			return CQAPI.SetGroupKick(AuthCode, GroupID, QQID, rejectaddrequest);
		}

		/// <summary>
		/// 日志——调试 灰色
		/// </summary>
		/// <param name="category"></param>
		/// <param name="content"></param>
		public void AddLogDEBUG(string category, string content)
		{
			CQAPI.AddLog(AuthCode, CQAPI.LogPriority.CQLOG_DEBUG, category, content);
		}

		/// <summary>
		/// 日志——警告 橙色
		/// </summary>
		/// <param name="category"></param>
		/// <param name="content"></param>
		public void AddLogWARNING(string category, string content)
		{
			CQAPI.AddLog(AuthCode, CQAPI.LogPriority.CQLOG_WARNING, category, content);
		}

		/// <summary>
		/// 输出一段日志
		/// </summary>
		/// <param name="content"></param>
		public void Log(string content)
		{
			CQAPI.AddLog(AuthCode, CQAPI.LogPriority.CQLOG_DEBUG, "Log", content);
		}

		/// <summary>
		/// 置致命提示错误
		/// </summary>
		/// <param name="code"></param>
		public void SetFatal(string code)
		{
			CQAPI.SetFatal(AuthCode, code);
		}

		/// <summary>
		/// 置好友添加请求
		/// </summary>
		/// <param name="responseflag"></param>
		/// <param name="responseoperation">1通过 2拒绝</param>
		/// <param name="remark">拒绝时的回应</param>
		public int SetFriendAddRequest(string responseflag, int responseoperation, string remark = "")
		{
			return CQAPI.SetFriendAddRequest(AuthCode, GB18030.GetBytes(responseflag), responseoperation, GB18030.GetBytes(remark));
		}

		/// <summary>
		/// 置加群请求处理
		/// </summary>
		/// <param name="responseflag"></param>
		/// <param name="requesttype"></param>
		/// <param name="responseoperation">1通过 2拒绝</param>
		/// <param name="reason">拒绝理由</param>
		/// <returns></returns>
		public int SetGroupAddRequest(string responseflag, int requesttype, int responseoperation, string reason = "")
		{
			return CQAPI.SetGroupAddRequestV2(AuthCode, GB18030.GetBytes(responseflag), requesttype, responseoperation, GB18030.GetBytes(reason));
		}

		private static byte[] Decoding_BASE64(string base64str)
		{
			//AAAAAQAUAAAAACKMLyoACrv6xvfIy7X3ytQ=
			byte[] str = System.Convert.FromBase64String(base64str);
			return str;
		}

		
	}
}
